/*
 * @Author       : Wang.XuanXuan xuanxuan.wang@wbstar.com
 * @Date         : 2024-05-20 22:11:04
 * @LastEditors  : Wang.XuanXuan xuanxuan.wang@wbstar.com
 * @LastEditTime : 2025-03-15 12:53:47
 * @FilePath     : \openchaoji-corelib\secc\utility\OpenChaoJi_secc_utility_linkage.h
 * @Description  : 本文件定义SECC Utility层 linkage 链路层协商和链路检测 模块
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef __OPEN_CHAOJI_SECC_UTILITY_LINKAGE_H__
#define __OPEN_CHAOJI_SECC_UTILITY_LINKAGE_H__

#include "../../shared/include/OpenChaoJi_shared.h"
#include "../include/OpenChaoJi_secc_hal.h"


#define LINKAGE_DEBUG_PRINTF_LOG_PERIOD	(20*1000)	//周期性打印log的时间, 这里是20s

#define LINKAGE_DEBUG

// 发送缓冲区最大发送长度
#define LINKAGE_SEND_MSG_MAX_LEN		(100)


#define LINKAGE_CONSULT_MSG_ID_PF	(0x38)
#define LINKAGE_CONSULT_MSG_ID_DP	(0)
#define LINKAGE_CONSULT_MSG_ID_EDP	(0)
#define LINKAGE_CONSULT_MSG_ID_P	(0x03)

// ReservedType
#define LINKAGE_RESERVED_TYPE		(0xFF)


// SECC版本协议报文的ID
#define LINKAGE_SECC_CONSULT_MSG_ID		( ( (OPENCHAOJI_GBT27930_B_CAN_ADDR_SECC & 0xFF) << 0) \
											+ ( (OPENCHAOJI_GBT27930_B_CAN_ADDR_EVCC & 0xFF) << 8) \
											+ ( (LINKAGE_CONSULT_MSG_ID_PF & 0xFF) << 16) \
											+ ( (LINKAGE_CONSULT_MSG_ID_P & 0x03) << 24) )
// EVCC版本协议报文的ID
#define LINKAGE_EVCC_CONSULT_MSG_ID		( ( (OPENCHAOJI_GBT27930_B_CAN_ADDR_SECC & 0xFF) << 8)  \
											+ ( (OPENCHAOJI_GBT27930_B_CAN_ADDR_EVCC & 0xFF) << 0)  \
											+ ( (LINKAGE_CONSULT_MSG_ID_PF & 0xFF) << 16) \
											+ ( (LINKAGE_CONSULT_MSG_ID_P & 0x03) << 24) )
// SECC版本协议报文的长度
#define LINKAGE_SECC_CONSULT_MSG_LEN		(8)

// EVCC版本协议报文的长度
#define LINKAGE_EVCC_CONSULT_MSG_LEN		(8)


// SECC版本协议报文的tag
#define LINKAGE_SECC_CONSULT_MSG_TAG		(0)

// EVCC版本协议报文的tag
#define LINKAGE_EVCC_CONSULT_MSG_TAG		(0)

// SECC版本协议报文的发送周期
#define LINKAGE_SECC_CONSULT_MSG_PERIOD		(50)


// 版本协议报文的超时时间
#define LINKAGE_CONSULT_MSG_TC_PERIOD		(5000)

// 链路检测: 没有其他报文发送的情况下, 重新发一次"版本协商"报文的超时时间
#define LINKAGE_WITNOUT_OTHER_MSG_T1_TIME	(1000)

// 链路检测: 没有应答的情况下, "链路检测"判定异常的最长时间
#define LINKAGE_WITNOUT_OTHER_MSG_T2_TIME	(3000)








// A/B系统共同讨论一个问题, CAN总线级别错误, HAL可以检测到, 是否需要上报, 链路层是否需要处理
// 0507 采用第三种方式, 由HAL跟App直接处理, CoreLib不处理. 后续如果讨论认为CoreLib需要根据链路状态来调整收发报文, 则通过在传输层做补丁方式增添功能

// A类系统未定义链路超时处理逻辑, 原则上本模块不需要处理

// B类系统的版本协商, 27930放在了链路层处理, 但是从逻辑和代码处理上来说, 放在B类系统的应用层作为一个模块处理更合适, 代码更清晰, 需要大家讨论一下
// 0507 应用层在功能协商加一步版本协商过程, 由System B通过会话层触发链路层进行版本协商, 并定时获取版本协商结果

// B类系统的通信链路检测27930描述了, 为本模块重点处理

// 会话层模块需要调用本模块和导引模块来确认当前系统的可运行状态


/**
 * @brief 本模块的上下文数据结构
 */
struct OpenChaoJi_secc_context_utility_linkage;



/**
 * @brief 创建本模块的上下文时需要传入的参数
 */
struct OpenChaoJi_secc_create_info_utility_linkage {

	union
	{
		struct {
			int dummy;
		} gbt27930_a;

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
		struct {
			enum OpenChaoJi_gbt27930_b_CANType can_type;

			/* 本SECC使用的版本号 */
			int secc_version;
		} gbt27930_b;
#endif
	} gbt27930_info;

	/**
     * 标识号, 用于debug打印, 一般是序号
    */
    int tag;

    /**
     * 应用启动创建上下文时, 各集成厂家可以传一个与本库无关的静态数据指针, 本库将保存该指针
     * 当app/hal层使用上下文时, 各集成厂家可以自行读取该数据
     * 一般最佳实践是传递本secc对应的索引序号, IO-MAP等
    */
    OpenChaoJi_hal_handle hal_handle;

    /**
     * 本SECC使用的系统类型, 目前仅支持B类, A类不需要链路检测
    */
    enum OpenChaoJi_secc_gbt27930_type secc_gbt27930_type;

};

// 版本协商子步骤
enum OpenChaoJi_secc_utility_linkage_version_confirm_step {
	OPENCHAOJI_SECC_LINKAGE_VERSION_CONFER_STEP_INIT = 0,			// S0 等待S1闭合后, 初始化初始化定时器, 并开始发送"充电机协议版本帧"
	OPENCHAOJI_SECC_LINKAGE_VERSION_CONFER_STEP_ING,				// S1 协商中
	OPENCHAOJI_SECC_LINKAGE_VERSION_CONFER_STEP_SUCCEED,			// S2 协商成功, 可以开始进行链路检测+进入功能协商功能模块FDC, 等待S1断开回到INIT
	OPENCHAOJI_SECC_LINKAGE_VERSION_CONFER_STEP_FAILED,				// S3 协商失败, 等待S1断开回到INIT
};


// 链路检测子步骤
enum OpenChaoJi_secc_utility_linkage_link_check_step {
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_STEP_INIT = 0,				// S0 初始化(等待协议版本协商通过)
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_STEP_UNTRUSTABLE,			// S1 通信链路状态不可信
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_STEP_NORMAL,					// S2 通信链路状态正常
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_STEP_ABNORMAL,				// S3 通信链路状态不正常
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_STEP_END,					// S4 退出检测(貌似没有必要)
};


// 链路检测开始标识
enum OpenChaoJi_secc_utility_linkage_link_check_flag {
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_FLAG_STOP = 0,				// 未开始检测
	OPENCHAOJI_SECC_LINKAGE_LINK_CHECK_FLAG_START,					// 开始检测
};

enum OpenChaoJi_secc_utility_linkage_version_res_type {
	OPENCHAOJI_SECC_LINKAGE_VER_RES_CONTINUE = 0,					// 版本协商结果: 继续协商
	OPENCHAOJI_SECC_LINKAGE_VER_RES_SUCCEED,						// 版本协商结果: 成功
	OPENCHAOJI_SECC_LINKAGE_VER_RES_FAILED,							// 版本协商结果: 失败
};


// 表40/41的处理逻辑应当在本模块自动完成
// 所以本模块需要至少两个接口, 一个是初始化协议版本帧, 用于T1定时器到的时候发送, 一个是收到对端数据的触发函数用于重置T1/T2
// 传递参数为上下文, 不是void

/**
 * @brief 初始化
 *
 * @param info 初始化信息
 * @return 成功返回创建的上下文指针，失败返回NULL。
 */
struct OpenChaoJi_secc_context_utility_linkage * OpenChaoJi_secc_utility_linkage_init(const struct OpenChaoJi_secc_create_info_utility_linkage * info);

/**
 * @brief 销毁
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_linkage_term(struct OpenChaoJi_secc_context_utility_linkage * context);

/**
 * @brief 复位
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_linkage_reset(struct OpenChaoJi_secc_context_utility_linkage * context);

/**
 * @brief 启动链路版本协商和链路检测
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param write_func 发送数据的方法, 用于发送版本协商和链路检测数据包
 * @param param write_func方法所需要的私有参数, 一般是传输层句柄
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_linkage_start(struct OpenChaoJi_secc_context_utility_linkage * context
		, int (*write_func)(void *param, struct OpenChaoJi_utility_data_buff_send_data * send_data), void * param);

/**
 * @brief 停止链路检测和版本协商(如存在)
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_secc_utility_linkage_stop(struct OpenChaoJi_secc_context_utility_linkage * context);

/**
 * @brief 服务, 链路版本协商和链路检测存在异步处理, 所以每次service触发内部处理
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
void OpenChaoJi_secc_utility_linkage_service(struct OpenChaoJi_secc_context_utility_linkage * context);

/**
 * @brief 收到数据, 版本协商或者链路检测相关数据帧需要交给本模块处理. 如果不是链路层数据, 则只更新链路超时计时器
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param recv_data 收到的链路层数据
 * @return 本模块已接收返回1，本模块未处理返回0。
 */
int OpenChaoJi_secc_utility_linkage_got_data(struct OpenChaoJi_secc_context_utility_linkage * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data);

/**
 * @brief 收到数据, 描述是否是链路检测模块所需要的数据
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param recv_data 收到的链路层数据
 * @return 本模块已接收返回1, 本模块未处理返回0。
 */
int OpenChaoJi_secc_utility_linkage_is_linkage_data(struct OpenChaoJi_secc_context_utility_linkage * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data);

/**
 * @brief 收到通信报文, 通知链路检测, 用于刷新检测通信链路断开的超时时间
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param last_ticks 最后一次收到通信报文的systick
 * @return 本模块无异常返回0, 有异常返回其他值。
 */
int OpenChaoJi_secc_utility_linkage_revc_data_ticks(struct OpenChaoJi_secc_context_utility_linkage * context, uint32_t last_ticks);

/**
 * @brief 上传发送数据调用该接口, 如果上次长时间没有发送数据, 链路检测则发送"版本协商"报文
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param last_ticks 最后一次发送数据的时间
 * @return 本模块已接收返回1，本模块未处理返回0。
 */
int OpenChaoJi_secc_utility_linkage_send_data_ticks(struct OpenChaoJi_secc_context_utility_linkage * context, uint32_t last_ticks);

/**
 * @brief B系统链路版本协商结果获取函数
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 返回版本协商状态
 */
enum OpenChaoJi_secc_utility_linkage_version_confirm_step OpenChaoJi_secc_utility_linkage_get_version_confer_state(struct OpenChaoJi_secc_context_utility_linkage * context);

/**
 * @brief B系统链路检测结果获取函数
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 返回链路检测结果
 */
enum OpenChaoJi_secc_utility_linkage_link_check_step OpenChaoJi_secc_utility_linkage_get_link_check_state(struct OpenChaoJi_secc_context_utility_linkage * context);


#endif
